#ifndef _THREADPOOL_H
#define _THREADPOOL_H

#include <iostream>
#include <queue>
#include <unistd.h>
#include <pthread.h>

template<class T>
class ThreadPool
{
    private:
        int _num;
        pthread_mutex_t mtx;
        pthread_cond_t ept;
        std::queue<T> task_queue;

    public:
        ThreadPool(int num = 5)
            :_num(num)
        {
            mtx = PTHREAD_MUTEX_INITIALIZER;
            ept = PTHREAD_COND_INITIALIZER;
        }

        static void* Routine(void* arg)
        {
            pthread_detach(pthread_self());
             

            return nullptr;
        }

        void Init()
        {
            for(volatile long i = 0; i < _num; ++i)
            {
                pthread_t tid;
                pthread_create(&tid, nullptr, Routine, nullptr);
            }
        }

        void Push(T& t)
        {
            Lock();
            task_queue.push(t);
            WakeUp();
            Unlock();
        }

        void Pop(T& t)
        {
            if(task_queue.size() == 0)
            {
                Wait();
                // 使用while防止发生伪唤醒
                while(task_queue.size() > 0)
                {
                    Lock();
                    t = task_queue.front();
                    task_queue.pop();
                    Unlock();
                }
            }
        }

        void Lock()
        {
            pthread_mutex_lock(&mtx);
        }

        void Unlock()
        {
            pthread_mutex_unlock(&mtx); 
        }

        void Wait()
        {
            pthread_cond_wait(&ept, &mtx);
        }

        void WakeUp()
        {
            Signal();
            // BroadCast();
        }

        void Signal()
        {
            pthread_cond_signal(&ept);
        }

        void BroadCast()
        {
            pthread_cond_broadcast(&ept);
        }
        
        ~ThreadPool(){}
};

#endif
